<?php
class AmapService
{

    /**
     * 地理编码
     */
    const AMAP_GEOCODE = 'https://restapi.amap.com/v3/geocode/geo';

    /**
     * 逆地理编码
     */
    const AMAP_REGEOCODE = 'https://restapi.amap.com/v3/geocode/regeo';

    const INFO_TEXT = [
        'OK'    =>  '获取成功',
        'INVALID_USER_KEY' => 'key不正确或过期',
        'SERVICE_NOT_AVAILABLE' => '没有权限使用相应的服务或者请求接口的路径拼写错误',
        'DAILY_QUERY_OVER_LIMIT' => '访问已超出日访问量',
        'ACCESS_TOO_FREQUENT' => '单位时间内访问过于频繁',
        'INVALID_USER_IP' => 'IP白名单出错，发送请求的服务器IP不在IP白名单内',
        'INVALID_USER_DOMAIN' => '绑定域名无效',
        'INVALID_USER_SIGNATURE' => '数字签名未通过验证',
        'INVALID_USER_SCODE' => 'MD5安全码未通过验证',
        'USERKEY_PLAT_NOMATCH' => '请求key与绑定平台不符',
        'IP_QUERY_OVER_LIMIT' => 'IP访问超限',
        'NOT_SUPPORT_HTTPS' => '服务不支持https请求',
        'INSUFFICIENT_PRIVILEGES' => '权限不足，服务请求被拒绝',
        'USER_KEY_RECYCLED' => 'Key被删除',
        'QPS_HAS_EXCEEDED_THE_LIMIT' => '云图服务QPS超限',
        'GATEWAY_TIMEOUT' => '受单机QPS限流限制',
        'SERVER_IS_BUSY' => '服务器负载过高',
        'RESOURCE_UNAVAILABLE' => '所请求的资源不可用',
        'CQPS_HAS_EXCEEDED_THE_LIMIT' => '使用的某个服务总QPS超限',
        'CKQPS_HAS_EXCEEDED_THE_LIMIT' => '某个Key使用某个服务接口QPS超出限制',
        'CUQPS_HAS_EXCEEDED_THE_LIMIT ' => '账号使用某个服务接口QPS超出限制',
        'INVALID_REQUEST' => '账号处于被封禁状态',
        'ABROAD_DAILY_QUERY_OVER_LIMIT' => '某个Key的QPS超出限制',
        'NO_EFFECTIVE_INTERFACE' => '请求的接口权限过期',
        'USER_DAILY_QUERY_OVER_LIMIT' => '账号维度日调用量超出限制',
        'USER_ABROAD_DAILY_QUERY_OVER_LIMIT' => '账号维度海外服务日调用量超出限制',
        'INVALID_PARAMS' => '请求参数非法',
        'MISSING_REQUIRED_PARAMS' => '缺少必填参数',
        'ILLEGAL_REQUEST' => '请求协议非法',
        'UNKNOWN_ERROR' => '其他未知错误',
        'INSUFFICIENT_ABROAD_PRIVILEGES' => '查询坐标或规划点（包括起点、终点、途经点）在海外，但没有海外地图权限',
        'ILLEGAL_CONTENT' => '查询信息存在非法内容',
        'OUT_OF_SERVICE' => '规划点（包括起点、终点、途经点）不在中国陆地范围内',
        'NO_ROADS_NEARBY' => '划点（起点、终点、途经点）附近搜不到路',
        'ROUTE_FAIL' => '路线计算失败，通常是由于道路连通关系导致',
        'OVER_DIRECTION_RANGE' => '起点终点距离过长。',
        'ENGINE_RESPONSE_DATA_ERROR' => '服务响应失败。',
        'QUOTA_PLAN_RUN_OUT' => '余额耗尽',
        'GEOFENCE_MAX_COUNT_REACHED' => '围栏个数达到上限',
        'SERVICE_EXPIRED' => '购买服务到期',
        'ABROAD_QUOTA_PLAN_RUN_OUT' => '海外服务余额耗尽',
    ];

    private $apiKey;

    public function __construct($apiKey = '5e0d711dc520a746549847425fc5465f')
    {
        $this->apiKey = $apiKey;
    }

    /**
     * 地理编码
     * 将详细的结构化地址转换为高德经纬度坐标。且支持对地标性名胜景区、建筑物名称解析为高德经纬度坐标。 
     * 举例：北京市朝阳区阜通东大街6号转换后经纬度：116.480881,39.989410  地标性建筑举例：天安门转换后经纬度：116.397499,39.908722
     * @return array|bool|mixed
     */
    public function geocode($address)
    {
        $param = [
            'address' => $address,
            'key' => $this->apiKey
        ];

        $result = self::curlGet(self::AMAP_GEOCODE, $param);
        if (isset($result['info'])) $result['message'] = self::INFO_TEXT[$result['info']];
        if (!isset($result['info'])) $result['message'] = isset($result['message']) ? $result['message'] : '获取失败';
        return $result;
    }

    /**
     * 逆地理编码
     * 将经纬度转换为详细结构化的地址，且返回附近周边的 POI、AOI 信息。 
     * 举例：116.480881,39.989410 转换地址描述后：北京市朝阳区阜通东大街6号
     * @return array|bool|mixed
     */
    public function regeocode($location)
    {
        $param = [
            'location' => $location,
            'key' => $this->apiKey
        ];

        $result = self::curlGet(self::AMAP_REGEOCODE, $param);
        if (isset($result['info'])) $result['message'] = self::INFO_TEXT[$result['info']];
        if (!isset($result['info'])) $result['message'] = isset($result['message']) ? $result['message'] : '获取失败';
        return $result;
    }

    /**
     * Curl Get请求
     * @params 输入的参数
     */
    protected function curlGet($url = '', $params = [], $timout = 5)
    {
        // 提供了参数，则构建带参数的URL
        if ($params) {
            $paramStr = '';
            foreach ($params as $key => $val) {
                $paramStr .= '&' . $key . '=' . $val;
            }

            $url .= '?' . $paramStr;
        }

        //初始化
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        //设置头文件的信息作为数据流输出
        curl_setopt($ch, CURLOPT_HEADER, false);
        //设置获取的信息以文件流的形式返回，而不是直接输出。
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        //在HTTP请求中包含一个”user-agent”头的字符串
        //curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36');
        // 设置请求超时时间
        curl_setopt($ch, CURLOPT_TIMEOUT, $timout);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
            //'X-Forwarded-For: 119.57.114.27',   // 伪造IP
            'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36'
        ));
        $output = curl_exec($ch);
        curl_close($ch);
        return $output ? json_decode($output, true) : '';
    }
}
